import datetime
import pandas as pd
import matplotlib.pyplot as plt
import statistics
from pathlib import Path
from typing import List, Dict, Tuple
from lw_config import config_util

# 全局样式配置
plt.rcParams.update({
    'font.family': 'Helvetica',
    'axes.labelcolor': '#333333',
    'axes.edgecolor': '#666666',
    'xtick.color': '#666666',
    'ytick.color': '#666666'
})


def process_weight_data(row: pd.Series) -> Tuple[float, bool]:
    """处理体重数据并验证有效性"""
    measurements = []
    for col in ['体重1', '体重2']:
        value = row[col]
        try:
            if pd.notna(value) and value != 0:
                measurements.append(float(value))
        except (ValueError, TypeError):
            continue
    return round(statistics.mean(measurements), 1) if measurements else None


def generate_chart(sheet_name: str, dates: List[str], weights: List[float]) -> None:
    """生成优化后的可视化图表"""
    plt.figure(figsize=(12, 6.5), dpi=150)
    ax = plt.gca()

    # 绘制主趋势线
    line, = ax.plot(dates, weights,
                    marker='o',
                    markersize=6,
                    linewidth=1.8,
                    color='#1f77b4',
                    markerfacecolor='white',
                    markeredgewidth=1.2)

    # 标注系统配置
    max_weight = max(weights)
    min_weight = min(weights)
    avg_weight = round(statistics.mean(weights), 1)

    # 动态标注引擎
    for idx, (date, weight) in enumerate(zip(dates, weights)):
        # 基础定位参数
        vertical_offset = 0.35 * (-1 if idx % 2 else 1)
        va_position = 'bottom' if weight < avg_weight else 'top'
        label_color = '#2c2c2c'

        # 极值特殊处理
        if weight in (max_weight, min_weight):
            vertical_offset *= 2.5
            label_color = '#d62728'
            ax.annotate(f'{weight}',
                        xy=(date, weight),
                        xytext=(date, weight + (2.8 if weight == max_weight else -2.8)),
                        arrowprops=dict(arrowstyle="->", color=label_color, alpha=0.8),
                        color=label_color,
                        fontsize=10,
                        ha='center',
                        zorder=5)

        # 数值标注
        ax.text(date, weight + vertical_offset, f'{weight}',
                ha='center',
                va=va_position,
                fontsize=9,
                color=label_color,
                bbox=dict(boxstyle='round,pad=0.2',
                          facecolor='white',
                          edgecolor='none',
                          alpha=0.7),
                zorder=4)

    # 平均线优化
    avg_line = ax.axhline(avg_weight,
                          color='#2ca02c',
                          linestyle='--',
                          linewidth=1.2,
                          alpha=0.8)
    ax.text(len(dates) - 0.8, avg_weight + 0.2, f'Avg: {avg_weight}',
            ha='right',
            color='#2ca02c',
            fontsize=10,
            backgroundcolor='white')

    # 图表装饰
    ax.set_title(sheet_name, pad=15, fontsize=14, color='#333333')
    ax.set_xlabel('Date', labelpad=10)
    ax.set_ylabel('Weight', labelpad=12)
    plt.xticks(rotation=38, ha='right')
    plt.grid(axis='y', linestyle=':', alpha=0.4)

    # 边距优化
    plt.margins(x=0.03, y=0.08)
    plt.tight_layout()

    # 保存输出
    output_dir = Path('./png/month/')
    output_dir.mkdir(parents=True, exist_ok=True)
    plt.savefig(output_dir / f'{sheet_name}.png',
                bbox_inches='tight',
                facecolor='white')
    plt.close()


def main():
    file_path = config_util.get_2025_execl()
    all_sheets = pd.read_excel(file_path, sheet_name=None, keep_default_na=False)

    for sheet_name, df in all_sheets.items():
        valid_dates = []
        valid_weights = []

        for _, row in df.dropna(how='all').iterrows():
            date_str = str(row.get('日期', ''))[:10]
            if not date_str or date_str.lower() == 'nan':
                continue

            weight = process_weight_data(row)
            if weight:
                valid_dates.append(date_str)
                valid_weights.append(weight)

        if len(valid_weights) >= 3:  # 至少3个有效数据点
            generate_chart(sheet_name, valid_dates, valid_weights)
        else:
            print(f'[{sheet_name}] 有效数据不足: {len(valid_weights)}个测量值')


if __name__ == '__main__':
    print(f'处理2025年月数据{datetime.datetime.now().strftime("%Y-%m")}')
    main()
